/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package moodlerest;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Hashtable;
import java.util.Vector;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

/**
 * Class containing the static routines used to create or update Moodle courses.
 * @see MoodleCourse
 * @author Bill Antonia
 */
public class MoodleRestCourse {

    private static final int BUFFER_MAX=4000;

    public MoodleRestCourse(){}

    /**
     * Method to return an array of MoodleCourse objects of all courses within the installation.
     * @return MoodleCourse[]
     * @throws MoodleRestCourseException
     * @throws UnsupportedEncodingException
     */
    public static MoodleCourse[] getAllCourses() throws MoodleRestCourseException, UnsupportedEncodingException {
        Vector v=new Vector();
        MoodleCourse course=null;
        StringBuilder data=new StringBuilder();
        if (MoodleRestWebService.getAuth()==null)
            throw new MoodleRestCourseException();
        else
            data.append(MoodleRestWebService.getAuth());
        data.append("&").append(URLEncoder.encode("wsfunction", "UTF-8")).append("=").append(URLEncoder.encode("moodle_course_get_courses", "UTF-8"));
        data.append("&").append(URLEncoder.encode("options[ids]", "UTF-8"));
        Document document = MoodleRestWebService.call(data.toString());
        NodeList elements = Util.getValueElementsFromXML(document);
        course=null;
        for (int j=0;j<elements.getLength();j++) {
            String content=elements.item(j).getTextContent();
            String nodeName=elements.item(j).getParentNode().getAttributes().getNamedItem("name").getNodeValue();
            if (nodeName.equals("id")) {
                if (course==null)
                    course=new MoodleCourse(Long.parseLong(content));
                else {
                    v.add(course);
                    course=new MoodleCourse(Long.parseLong(content));
                }
            }
            course.setMoodleCourseField(nodeName, content);
        }
        if (course!=null)
            v.add(course);
        MoodleCourse[] courses=new MoodleCourse[v.size()];
        for (int i=0;i<v.size();i++) {
            courses[i]=(MoodleCourse)v.get(i);
        }
        v.removeAllElements();
        return courses;
    }

    /**
     *
     * @param id Moodle id of the course to fetch
     * @return MoodleCourse object
     * @throws MoodleRestCourseException
     * @throws UnsupportedEncodingException
     */
    public static MoodleCourse getCourseFromId(long id) throws MoodleRestCourseException, UnsupportedEncodingException {
        long[] a=new long[1];
        a[0]=id;
        MoodleCourse[] crs=getCoursesById(a);
        return crs[0];
    }

    /**
     *
     * @param courseids Array of Moodle course ids
     * @return MoodleCourse[] Array of MoodleCourse objects
     * @throws MoodleRestCourseException
     * @throws UnsupportedEncodingException
     */
    public static MoodleCourse[] getCoursesById(long[] courseids) throws MoodleRestCourseException, UnsupportedEncodingException{
        Vector v=new Vector();
        MoodleCourse course=null;
        boolean processed=false;
        StringBuilder data=new StringBuilder();
        if (MoodleRestWebService.getAuth()==null)
            throw new MoodleRestCourseException();
        else
            data.append(MoodleRestWebService.getAuth());
        data.append("&").append(URLEncoder.encode("wsfunction", "UTF-8")).append("=").append(URLEncoder.encode("moodle_course_get_courses", "UTF-8"));
        for (int i=0;i<courseids.length;i++) {
            if (courseids[i]<1) throw new MoodleRestCourseException(); data.append("&").append(URLEncoder.encode("options[ids]["+i+"]", "UTF-8")).append("=").append(courseids[i]);
            if (data.length()>=BUFFER_MAX) {
                processed=true;
                data.trimToSize();
                Document document = MoodleRestWebService.call(data.toString());
                NodeList elements = Util.getValueElementsFromXML(document);
                course=null;
                for (int j=0;j<elements.getLength();j++) {
                    String content=elements.item(j).getTextContent();
                    String nodeName=elements.item(j).getParentNode().getAttributes().getNamedItem("name").getNodeValue();
                    if (nodeName.equals("id")) {
                        if (course==null)
                            course=new MoodleCourse(Long.parseLong(content));
                        else {
                            v.add(course);
                            course=new MoodleCourse(Long.parseLong(content));
                        }
                    }
                    course.setMoodleCourseField(nodeName, content);
                }
                data=new StringBuilder();
                data.append(MoodleRestWebService.getAuth());
                data.append("&").append(URLEncoder.encode("wsfunction", "UTF-8")).append("=").append(URLEncoder.encode("moodle_course_get_courses", "UTF-8"));
            } else
                processed=false;
        }
        if (!processed) {
            data.trimToSize();
            Document document = MoodleRestWebService.call(data.toString());
            NodeList elements = Util.getValueElementsFromXML(document);
            course=null;
            for (int j=0;j<elements.getLength();j++) {
                String content=elements.item(j).getTextContent();
                String nodeName=elements.item(j).getParentNode().getAttributes().getNamedItem("name").getNodeValue();
                if (nodeName.equals("id")) {
                    if (course==null)
                        course=new MoodleCourse(Long.parseLong(content));
                    else {
                        v.add(course);
                        course=new MoodleCourse(Long.parseLong(content));
                    }
                }
                course.setMoodleCourseField(nodeName, content);
            }
        }
        if (course!=null)
            v.add(course);
        MoodleCourse[] courses=new MoodleCourse[v.size()];
        for (int i=0;i<v.size();i++) {
            courses[i]=(MoodleCourse)v.get(i);
        }
        v.removeAllElements();
        return courses;
    }

    /**
     *
     * @param course MoodleCourse object. Needs to have shortname,fullname and categoryid completed before this call.
     * @return MoodleCourse object with the id updated to the course id within Moodle.
     * @throws MoodleRestCourseException
     * @throws UnsupportedEncodingException
     */
    public static MoodleCourse createCourse(MoodleCourse course) throws MoodleRestCourseException, UnsupportedEncodingException {
        MoodleCourse[] a=new MoodleCourse[1];
        a[0]=course;
        MoodleCourse[] crs=createCourses(a);
        return crs[0];
    }

    /**
     *
     * @param course MoodleCourse[]. Array of MoodleCourse each initialised with shortname,fullname and categoryid before the call.
     * @return MoodleCourse[]. Updated array, each MoodleCourse object within the array having their id values updated to that in Moodle.
     * @throws MoodleRestCourseException
     * @throws UnsupportedEncodingException
     */
    public static MoodleCourse[] createCourses(MoodleCourse[] course) throws MoodleRestCourseException, UnsupportedEncodingException {
        Hashtable hash=new Hashtable();
        boolean processed=false;
        StringBuilder data=new StringBuilder();
        if (MoodleRestWebService.getAuth()==null)
            throw new MoodleRestCourseException();
        else
            data.append(MoodleRestWebService.getAuth());
        data.append("&").append(URLEncoder.encode("wsfunction", "UTF-8")).append("=").append(URLEncoder.encode("moodle_course_create_courses", "UTF-8"));
        for (int i=0;i<course.length;i++) {
            if (course[i]==null) throw new MoodleRestCourseException();
            if (course[i].getShortname()==null) throw new MoodleRestCourseException(); else data.append("&").append(URLEncoder.encode("courses["+i+"][shortname]", "UTF-8")).append("=").append(URLEncoder.encode(course[i].getShortname(), "UTF-8"));
            if (course[i].getFullname()==null) throw new MoodleRestCourseException(); else data.append("&").append(URLEncoder.encode("courses["+i+"][fullname]", "UTF-8")).append("=").append(URLEncoder.encode(course[i].getFullname(), "UTF-8"));
            if (course[i].getCategoryId()==-1) throw new MoodleRestCourseException(); else data.append("&").append(URLEncoder.encode("courses["+i+"][categoryid]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getCategoryId(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][summaryformat]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getSummaryFormat(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][format]", "UTF-8")).append("=").append(URLEncoder.encode(course[i].getFormat(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][showgrades]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getShowGrades(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][newsitems]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getNewsItems(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][numsections]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getNumSections(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][maxbytes]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getMaxBytes(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][showreports]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getShowReports(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][hiddensections]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getHiddenSections(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][groupmode]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getGroupMode(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][groupmodeforce]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getGroupModeForce(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][defaultgroupingid]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getDefaultGroupingId(), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][enablecompletion]", "UTF-8")).append("=").append(URLEncoder.encode(""+(course[i].getEnableCompletion()?1:0), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][completionstartonenrol]", "UTF-8")).append("=").append(URLEncoder.encode(""+(course[i].getCompletionStartOnEnrol()?1:0), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][completionnotify]", "UTF-8")).append("=").append(URLEncoder.encode(""+(course[i].getCompletionNotify()?1:0), "UTF-8"));
            data.append("&").append(URLEncoder.encode("courses["+i+"][visible]", "UTF-8")).append("=").append(URLEncoder.encode(""+(course[i].getVisible()?1:0), "UTF-8"));
            if (course[i].getSummary()!=null) data.append("&").append(URLEncoder.encode("courses["+i+"][summary]", "UTF-8")).append("=").append(URLEncoder.encode(course[i].getSummary(), "UTF-8"));
            if (course[i].getIdNumber()!=null) data.append("&").append(URLEncoder.encode("courses["+i+"][idnumber]", "UTF-8")).append("=").append(URLEncoder.encode(course[i].getIdNumber(), "UTF-8"));
            if (course[i].getLang()!=null) data.append("&").append(URLEncoder.encode("courses["+i+"][lang]", "UTF-8")).append("=").append(URLEncoder.encode(course[i].getLang(), "UTF-8"));
            if (course[i].getForceTheme()!=null) data.append("&").append(URLEncoder.encode("courses["+i+"][forcetheme]", "UTF-8")).append("=").append(URLEncoder.encode(course[i].getForceTheme(), "UTF-8"));
            if (course[i].getStartDate()!=-1) data.append("&").append(URLEncoder.encode("courses["+i+"][startdate]", "UTF-8")).append("=").append(URLEncoder.encode(""+course[i].getStartDate(), "UTF-8"));
            if (data.length()>=BUFFER_MAX) {
                processed=true;
                data.trimToSize();
                Document document = MoodleRestWebService.call(data.toString());
                NodeList elements = Util.getValueElementsFromXML(document);
                for (int j=0;j<elements.getLength();j+=2) {
                    hash.put(elements.item(j+1).getTextContent(), elements.item(j).getTextContent());
                }
                data=new StringBuilder();
                data.append(MoodleRestWebService.getAuth());
                data.append("&").append(URLEncoder.encode("wsfunction", "UTF-8")).append("=").append(URLEncoder.encode("moodle_course_create_courses", "UTF-8"));
            } else
                processed=false;
        }
        if (!processed) {
            data.trimToSize();
            Document document = MoodleRestWebService.call(data.toString());
            NodeList elements = Util.getValueElementsFromXML(document);
            for (int j=0;j<elements.getLength();j+=2) {
                hash.put(elements.item(j+1).getTextContent(), elements.item(j).getTextContent());
            }
        }
        for (int i=0;i<course.length;i++) {
            if (hash.containsKey(course[i].getShortname()))
                course[i].setId(Long.parseLong((String)(hash.get(course[i].getShortname()))));
            else
                course[i]=null;
        }
        return course;
    }
}
